package cn.yeziji.forum.utils;

import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 列表工具类
 *
 * @author gzkemays
 * @since 2022/4/22 8:55
 */
public class ListsCollect<T> {
  private final List<T> value;

  public ListsCollect(List<T> value) {
    this.value = value;
  }

  public static <T> ListsCollect<T> objCollect(Object value, Class<T> clazz) {
    return new ListsCollect<>(castList(value, clazz));
  }

  public static <T> List<T> cast(Object value, Class<T> clazz) {
    return castList(value, clazz);
  }

  public static ListsCollect<String> splitStr(String str, String split) {
    return new ListsCollect(Arrays.asList(str.split(split)));
  }

  public static <T> ListsCollect<T> of(List<T> value) {
    return new ListsCollect<>(value);
  }

  public List<T> orElse(List<T> other) {
    return !CollectionUtils.isEmpty(value) ? value : other;
  }

  public List<T> orElseGet(Supplier<? extends List<T>> other) {
    return CollectionUtils.isEmpty(value) ? value : other.get();
  }

  public List<T> orElseEmpty() {
    return orElse(new ArrayList<>());
  }

  public List<T> notContainerAdd(T add) {
    List<T> ts = orElseEmpty();
    if (!ts.contains(add)) {
      ts.add(add);
    }
    return ts;
  }

  public List<T> newNotContainerAdd(T add) {
    List<T> newList = new ArrayList<>(orElseEmpty());
    if (!newList.contains(add)) {
      newList.add(add);
    }
    return newList;
  }

  public static boolean isNotEmpty(Collection<?> list) {
    return list != null && !list.isEmpty();
  }

  public boolean isNotEmpty() {
    return isNotEmpty(value);
  }

  public ListsCollect<T> notEmptyFunction(Function<List<T>, Object> function) {
    if (isNotEmpty()) {
      function.apply(value);
    }
    return this;
  }

  public ListsCollect<T> notEmptyConsumer(Consumer<List<T>> consumer) {
    if (isNotEmpty()) {
      consumer.accept(value);
    }
    return this;
  }

  public ListsCollect<T> notEmptyForConsumer(Consumer<T> consumer) {
    if (isNotEmpty()) {
      for (T t : value) {
        consumer.accept(t);
      }
    }
    return this;
  }

  public static boolean isEmpty(Collection<?> list) {
    return list == null || list.isEmpty();
  }

  public boolean isEmpty() {
    return isEmpty(value);
  }

  public static <T> List<T> emptyList() {
    return new ArrayList<>();
  }

  public Collection<T> getCollection() {
    return value;
  }

  public <EX extends Throwable> List<T> orElseThrow(Supplier<? extends EX> supplier) throws EX {
    if (!CollectionUtils.isEmpty(value)) {
      return value;
    } else {
      throw supplier.get();
    }
  }

  public static <T> List<T> castList(Object obj, Class<T> clazz) {
    List<T> result = new ArrayList<>();
    if (obj instanceof List<?>) {
      for (Object o : (List<?>) obj) {
        result.add(clazz.cast(o));
      }
      return result;
    }
    return null;
  }
}
